home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / SimpleXMLRPCServer.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-11-11  |  20KB  |  560 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. '''Simple XML-RPC Server.
  5.  
  6. This module can be used to create simple XML-RPC servers
  7. by creating a server and either installing functions, a
  8. class instance, or by extending the SimpleXMLRPCServer
  9. class.
  10.  
  11. It can also be used to handle XML-RPC requests in a CGI
  12. environment using CGIXMLRPCRequestHandler.
  13.  
  14. A list of possible usage patterns follows:
  15.  
  16. 1. Install functions:
  17.  
  18. server = SimpleXMLRPCServer(("localhost", 8000))
  19. server.register_function(pow)
  20. server.register_function(lambda x,y: x+y, \'add\')
  21. server.serve_forever()
  22.  
  23. 2. Install an instance:
  24.  
  25. class MyFuncs:
  26.     def __init__(self):
  27.         # make all of the string functions available through
  28.         # string.func_name
  29.         import string
  30.         self.string = string
  31.     def _listMethods(self):
  32.         # implement this method so that system.listMethods
  33.         # knows to advertise the strings methods
  34.         return list_public_methods(self) +                 [\'string.\' + method for method in list_public_methods(self.string)]
  35.     def pow(self, x, y): return pow(x, y)
  36.     def add(self, x, y) : return x + y
  37.  
  38. server = SimpleXMLRPCServer(("localhost", 8000))
  39. server.register_introspection_functions()
  40. server.register_instance(MyFuncs())
  41. server.serve_forever()
  42.  
  43. 3. Install an instance with custom dispatch method:
  44.  
  45. class Math:
  46.     def _listMethods(self):
  47.         # this method must be present for system.listMethods
  48.         # to work
  49.         return [\'add\', \'pow\']
  50.     def _methodHelp(self, method):
  51.         # this method must be present for system.methodHelp
  52.         # to work
  53.         if method == \'add\':
  54.             return "add(2,3) => 5"
  55.         elif method == \'pow\':
  56.             return "pow(x, y[, z]) => number"
  57.         else:
  58.             # By convention, return empty
  59.             # string if no help is available
  60.             return ""
  61.     def _dispatch(self, method, params):
  62.         if method == \'pow\':
  63.             return pow(*params)
  64.         elif method == \'add\':
  65.             return params[0] + params[1]
  66.         else:
  67.             raise \'bad method\'
  68.  
  69. server = SimpleXMLRPCServer(("localhost", 8000))
  70. server.register_introspection_functions()
  71. server.register_instance(Math())
  72. server.serve_forever()
  73.  
  74. 4. Subclass SimpleXMLRPCServer:
  75.  
  76. class MathServer(SimpleXMLRPCServer):
  77.     def _dispatch(self, method, params):
  78.         try:
  79.             # We are forcing the \'export_\' prefix on methods that are
  80.             # callable through XML-RPC to prevent potential security
  81.             # problems
  82.             func = getattr(self, \'export_\' + method)
  83.         except AttributeError:
  84.             raise Exception(\'method "%s" is not supported\' % method)
  85.         else:
  86.             return func(*params)
  87.  
  88.     def export_add(self, x, y):
  89.         return x + y
  90.  
  91. server = MathServer(("localhost", 8000))
  92. server.serve_forever()
  93.  
  94. 5. CGI script:
  95.  
  96. server = CGIXMLRPCRequestHandler()
  97. server.register_function(pow)
  98. server.handle_request()
  99. '''
  100. import xmlrpclib
  101. from xmlrpclib import Fault
  102. import SocketServer
  103. import BaseHTTPServer
  104. import sys
  105. import os
  106. import traceback
  107.  
  108. try:
  109.     import fcntl
  110. except ImportError:
  111.     fcntl = None
  112.  
  113.  
  114. def resolve_dotted_attribute(obj, attr, allow_dotted_names = True):
  115.     """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d
  116.  
  117.     Resolves a dotted attribute name to an object.  Raises
  118.     an AttributeError if any attribute in the chain starts with a '_'.
  119.  
  120.     If the optional allow_dotted_names argument is false, dots are not
  121.     supported and this function operates similar to getattr(obj, attr).
  122.     """
  123.     if allow_dotted_names:
  124.         attrs = attr.split('.')
  125.     else:
  126.         attrs = [
  127.             attr]
  128.     for i in attrs:
  129.         if i.startswith('_'):
  130.             raise AttributeError('attempt to access private attribute "%s"' % i)
  131.         i.startswith('_')
  132.         obj = getattr(obj, i)
  133.     
  134.     return obj
  135.  
  136.  
  137. def list_public_methods(obj):
  138.     '''Returns a list of attribute strings, found in the specified
  139.     object, which represent callable attributes'''
  140.     return _[1]
  141.  
  142.  
  143. def remove_duplicates(lst):
  144.     '''remove_duplicates([2,2,2,1,3,3]) => [3,1,2]
  145.  
  146.     Returns a copy of a list without duplicates. Every list
  147.     item must be hashable and the order of the items in the
  148.     resulting list is not defined.
  149.     '''
  150.     u = { }
  151.     for x in lst:
  152.         u[x] = 1
  153.     
  154.     return u.keys()
  155.  
  156.  
  157. class SimpleXMLRPCDispatcher:
  158.     '''Mix-in class that dispatches XML-RPC requests.
  159.  
  160.     This class is used to register XML-RPC method handlers
  161.     and then to dispatch them. There should never be any
  162.     reason to instantiate this class directly.
  163.     '''
  164.     
  165.     def __init__(self, allow_none = False, encoding = None):
  166.         self.funcs = { }
  167.         self.instance = None
  168.         self.allow_none = allow_none
  169.         self.encoding = encoding
  170.  
  171.     
  172.     def register_instance(self, instance, allow_dotted_names = False):
  173.         """Registers an instance to respond to XML-RPC requests.
  174.  
  175.         Only one instance can be installed at a time.
  176.  
  177.         If the registered instance has a _dispatch method then that
  178.         method will be called with the name of the XML-RPC method and
  179.         its parameters as a tuple
  180.         e.g. instance._dispatch('add',(2,3))
  181.  
  182.         If the registered instance does not have a _dispatch method
  183.         then the instance will be searched to find a matching method
  184.         and, if found, will be called. Methods beginning with an '_'
  185.         are considered private and will not be called by
  186.         SimpleXMLRPCServer.
  187.  
  188.         If a registered function matches a XML-RPC request, then it
  189.         will be called instead of the registered instance.
  190.  
  191.         If the optional allow_dotted_names argument is true and the
  192.         instance does not have a _dispatch method, method names
  193.         containing dots are supported and resolved, as long as none of
  194.         the name segments start with an '_'.
  195.  
  196.             *** SECURITY WARNING: ***
  197.  
  198.             Enabling the allow_dotted_names options allows intruders
  199.             to access your module's global variables and may allow
  200.             intruders to execute arbitrary code on your machine.  Only
  201.             use this option on a secure, closed network.
  202.  
  203.         """
  204.         self.instance = instance
  205.         self.allow_dotted_names = allow_dotted_names
  206.  
  207.     
  208.     def register_function(self, function, name = None):
  209.         '''Registers a function to respond to XML-RPC requests.
  210.  
  211.         The optional name argument can be used to set a Unicode name
  212.         for the function.
  213.         '''
  214.         if name is None:
  215.             name = function.__name__
  216.         
  217.         self.funcs[name] = function
  218.  
  219.     
  220.     def register_introspection_functions(self):
  221.         '''Registers the XML-RPC introspection methods in the system
  222.         namespace.
  223.  
  224.         see http://xmlrpc.usefulinc.com/doc/reserved.html
  225.         '''
  226.         self.funcs.update({
  227.             'system.listMethods': self.system_listMethods,
  228.             'system.methodSignature': self.system_methodSignature,
  229.             'system.methodHelp': self.system_methodHelp })
  230.  
  231.     
  232.     def register_multicall_functions(self):
  233.         '''Registers the XML-RPC multicall method in the system
  234.         namespace.
  235.  
  236.         see http://www.xmlrpc.com/discuss/msgReader$1208'''
  237.         self.funcs.update({
  238.             'system.multicall': self.system_multicall })
  239.  
  240.     
  241.     def _marshaled_dispatch(self, data, dispatch_method = None):
  242.         '''Dispatches an XML-RPC method from marshalled (XML) data.
  243.  
  244.         XML-RPC methods are dispatched from the marshalled (XML) data
  245.         using the _dispatch method and the result is returned as
  246.         marshalled data. For backwards compatibility, a dispatch
  247.         function can be provided as an argument (see comment in
  248.         SimpleXMLRPCRequestHandler.do_POST) but overriding the
  249.         existing method through subclassing is the prefered means
  250.         of changing method dispatch behavior.
  251.         '''
  252.         
  253.         try:
  254.             (params, method) = xmlrpclib.loads(data)
  255.             if dispatch_method is not None:
  256.                 response = dispatch_method(method, params)
  257.             else:
  258.                 response = self._dispatch(method, params)
  259.             response = (response,)
  260.             response = xmlrpclib.dumps(response, methodresponse = 1, allow_none = self.allow_none, encoding = self.encoding)
  261.         except Fault:
  262.             fault = None
  263.             response = xmlrpclib.dumps(fault, allow_none = self.allow_none, encoding = self.encoding)
  264.         except:
  265.             (exc_type, exc_value, exc_tb) = sys.exc_info()
  266.             response = xmlrpclib.dumps(xmlrpclib.Fault(1, '%s:%s' % (exc_type, exc_value)), encoding = self.encoding, allow_none = self.allow_none)
  267.  
  268.         return response
  269.  
  270.     
  271.     def system_listMethods(self):
  272.         """system.listMethods() => ['add', 'subtract', 'multiple']
  273.  
  274.         Returns a list of the methods supported by the server."""
  275.         methods = self.funcs.keys()
  276.         if self.instance is not None:
  277.             if hasattr(self.instance, '_listMethods'):
  278.                 methods = remove_duplicates(methods + self.instance._listMethods())
  279.             elif not hasattr(self.instance, '_dispatch'):
  280.                 methods = remove_duplicates(methods + list_public_methods(self.instance))
  281.             
  282.         
  283.         methods.sort()
  284.         return methods
  285.  
  286.     
  287.     def system_methodSignature(self, method_name):
  288.         """system.methodSignature('add') => [double, int, int]
  289.  
  290.         Returns a list describing the signature of the method. In the
  291.         above example, the add method takes two integers as arguments
  292.         and returns a double result.
  293.  
  294.         This server does NOT support system.methodSignature."""
  295.         return 'signatures not supported'
  296.  
  297.     
  298.     def system_methodHelp(self, method_name):
  299.         '''system.methodHelp(\'add\') => "Adds two integers together"
  300.  
  301.         Returns a string containing documentation for the specified method.'''
  302.         method = None
  303.         if method_name in self.funcs:
  304.             method = self.funcs[method_name]
  305.         elif self.instance is not None:
  306.             hasattr(self.instance, '_methodHelp') if hasattr(self.instance, '_methodHelp') else hasattr(self.instance, '_methodHelp')<EXCEPTION MATCH>AttributeError
  307.         
  308.         if method is None:
  309.             return ''
  310.         import pydoc as pydoc
  311.         return pydoc.getdoc(method)
  312.  
  313.     
  314.     def system_multicall(self, call_list):
  315.         """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => [[4], ...]
  316.  
  317.         Allows the caller to package multiple XML-RPC calls into a single
  318.         request.
  319.  
  320.         See http://www.xmlrpc.com/discuss/msgReader$1208
  321.         """
  322.         results = []
  323.         for call in call_list:
  324.             method_name = call['methodName']
  325.             params = call['params']
  326.             
  327.             try:
  328.                 results.append([
  329.                     self._dispatch(method_name, params)])
  330.             continue
  331.             except Fault:
  332.                 fault = None
  333.                 results.append({
  334.                     'faultCode': fault.faultCode,
  335.                     'faultString': fault.faultString })
  336.                 continue
  337.                 (exc_type, exc_value, exc_tb) = sys.exc_info()
  338.                 results.append({
  339.                     'faultCode': 1,
  340.                     'faultString': '%s:%s' % (exc_type, exc_value) })
  341.                 continue
  342.             
  343.  
  344.         
  345.         return results
  346.  
  347.     
  348.     def _dispatch(self, method, params):
  349.         """Dispatches the XML-RPC method.
  350.  
  351.         XML-RPC calls are forwarded to a registered function that
  352.         matches the called XML-RPC method name. If no such function
  353.         exists then the call is forwarded to the registered instance,
  354.         if available.
  355.  
  356.         If the registered instance has a _dispatch method then that
  357.         method will be called with the name of the XML-RPC method and
  358.         its parameters as a tuple
  359.         e.g. instance._dispatch('add',(2,3))
  360.  
  361.         If the registered instance does not have a _dispatch method
  362.         then the instance will be searched to find a matching method
  363.         and, if found, will be called.
  364.  
  365.         Methods beginning with an '_' are considered private and will
  366.         not be called.
  367.         """
  368.         func = None
  369.         
  370.         try:
  371.             func = self.funcs[method]
  372.         except KeyError:
  373.             if self.instance is not None:
  374.                 if hasattr(self.instance, '_dispatch'):
  375.                     return self.instance._dispatch(method, params)
  376.                 
  377.                 try:
  378.                     func = resolve_dotted_attribute(self.instance, method, self.allow_dotted_names)
  379.                 except AttributeError:
  380.                     hasattr(self.instance, '_dispatch')
  381.                     hasattr(self.instance, '_dispatch')
  382.                 except:
  383.                     hasattr(self.instance, '_dispatch')<EXCEPTION MATCH>AttributeError
  384.                 
  385.  
  386.             hasattr(self.instance, '_dispatch')<EXCEPTION MATCH>AttributeError
  387.         except:
  388.             hasattr(self.instance, '_dispatch')
  389.  
  390.         if func is not None:
  391.             return func(*params)
  392.         raise Exception('method "%s" is not supported' % method)
  393.  
  394.  
  395.  
  396. class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
  397.     '''Simple XML-RPC request handler class.
  398.  
  399.     Handles all HTTP POST requests and attempts to decode them as
  400.     XML-RPC requests.
  401.     '''
  402.     rpc_paths = ('/', '/RPC2')
  403.     
  404.     def is_rpc_path_valid(self):
  405.         if self.rpc_paths:
  406.             return self.path in self.rpc_paths
  407.         return True
  408.  
  409.     
  410.     def do_POST(self):
  411.         """Handles the HTTP POST request.
  412.  
  413.         Attempts to interpret all HTTP POST requests as XML-RPC calls,
  414.         which are forwarded to the server's _dispatch method for handling.
  415.         """
  416.         if not self.is_rpc_path_valid():
  417.             self.report_404()
  418.             return None
  419.         
  420.         try:
  421.             max_chunk_size = 10485760
  422.             size_remaining = int(self.headers['content-length'])
  423.             L = []
  424.             while size_remaining:
  425.                 chunk_size = min(size_remaining, max_chunk_size)
  426.                 L.append(self.rfile.read(chunk_size))
  427.                 size_remaining -= len(L[-1])
  428.                 continue
  429.                 self.is_rpc_path_valid()
  430.             data = ''.join(L)
  431.             response = self.server._marshaled_dispatch(data, getattr(self, '_dispatch', None))
  432.         except Exception:
  433.             self.is_rpc_path_valid()
  434.             e = self.is_rpc_path_valid()
  435.             self.send_response(500)
  436.             if hasattr(self.server, '_send_traceback_header') and self.server._send_traceback_header:
  437.                 self.send_header('X-exception', str(e))
  438.                 self.send_header('X-traceback', traceback.format_exc())
  439.             
  440.             self.end_headers()
  441.         except:
  442.             self.is_rpc_path_valid()
  443.  
  444.         self.send_response(200)
  445.         self.send_header('Content-type', 'text/xml')
  446.         self.send_header('Content-length', str(len(response)))
  447.         self.end_headers()
  448.         self.wfile.write(response)
  449.         self.wfile.flush()
  450.         self.connection.shutdown(1)
  451.  
  452.     
  453.     def report_404(self):
  454.         self.send_response(404)
  455.         response = 'No such page'
  456.         self.send_header('Content-type', 'text/plain')
  457.         self.send_header('Content-length', str(len(response)))
  458.         self.end_headers()
  459.         self.wfile.write(response)
  460.         self.wfile.flush()
  461.         self.connection.shutdown(1)
  462.  
  463.     
  464.     def log_request(self, code = '-', size = '-'):
  465.         '''Selectively log an accepted request.'''
  466.         if self.server.logRequests:
  467.             BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)
  468.         
  469.  
  470.  
  471.  
  472. class SimpleXMLRPCServer(SocketServer.TCPServer, SimpleXMLRPCDispatcher):
  473.     '''Simple XML-RPC server.
  474.  
  475.     Simple XML-RPC server that allows functions and a single instance
  476.     to be installed to handle requests. The default implementation
  477.     attempts to dispatch XML-RPC calls to the functions or instance
  478.     installed in the server. Override the _dispatch method inhereted
  479.     from SimpleXMLRPCDispatcher to change this behavior.
  480.     '''
  481.     allow_reuse_address = True
  482.     _send_traceback_header = False
  483.     
  484.     def __init__(self, addr, requestHandler = SimpleXMLRPCRequestHandler, logRequests = True, allow_none = False, encoding = None, bind_and_activate = True):
  485.         self.logRequests = logRequests
  486.         SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
  487.         SocketServer.TCPServer.__init__(self, addr, requestHandler, bind_and_activate)
  488.         if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'):
  489.             flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD)
  490.             flags |= fcntl.FD_CLOEXEC
  491.             fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags)
  492.         
  493.  
  494.  
  495.  
  496. class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher):
  497.     '''Simple handler for XML-RPC data passed through CGI.'''
  498.     
  499.     def __init__(self, allow_none = False, encoding = None):
  500.         SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding)
  501.  
  502.     
  503.     def handle_xmlrpc(self, request_text):
  504.         '''Handle a single XML-RPC request'''
  505.         response = self._marshaled_dispatch(request_text)
  506.         print 'Content-Type: text/xml'
  507.         print 'Content-Length: %d' % len(response)
  508.         print 
  509.         sys.stdout.write(response)
  510.  
  511.     
  512.     def handle_get(self):
  513.         '''Handle a single HTTP GET request.
  514.  
  515.         Default implementation indicates an error because
  516.         XML-RPC uses the POST method.
  517.         '''
  518.         code = 400
  519.         (message, explain) = BaseHTTPServer.BaseHTTPRequestHandler.responses[code]
  520.         response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % {
  521.             'code': code,
  522.             'message': message,
  523.             'explain': explain }
  524.         print 'Status: %d %s' % (code, message)
  525.         print 'Content-Type: text/html'
  526.         print 'Content-Length: %d' % len(response)
  527.         print 
  528.         sys.stdout.write(response)
  529.  
  530.     
  531.     def handle_request(self, request_text = None):
  532.         '''Handle a single XML-RPC request passed through a CGI post method.
  533.  
  534.         If no XML data is given then it is read from stdin. The resulting
  535.         XML-RPC response is printed to stdout along with the correct HTTP
  536.         headers.
  537.         '''
  538.         if request_text is None and os.environ.get('REQUEST_METHOD', None) == 'GET':
  539.             self.handle_get()
  540.         else:
  541.             
  542.             try:
  543.                 length = int(os.environ.get('CONTENT_LENGTH', None))
  544.             except (TypeError, ValueError):
  545.                 length = -1
  546.  
  547.             if request_text is None:
  548.                 request_text = sys.stdin.read(length)
  549.             
  550.             self.handle_xmlrpc(request_text)
  551.  
  552.  
  553. if __name__ == '__main__':
  554.     print 'Running XML-RPC server on port 8000'
  555.     server = SimpleXMLRPCServer(('localhost', 8000))
  556.     server.register_function(pow)
  557.     server.register_function((lambda x, y: x + y), 'add')
  558.     server.serve_forever()
  559.  
  560.